﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ViewCamera.Rgbd.CApRgbdConfigViewModel
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using System;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Media;
using Tecnomatix.Engineering;
using Tecnomatix.Engineering.Ui;
using Tecnomatix.Engineering.Ui.WPF;


namespace DnProcessSimulateCommands.ViewCamera.Rgbd;

internal class CApRgbdConfigViewModel : TxViewModelBase
{
  private double MIN_RATIO = 0.25;
  private double MAX_RATIO = 8.0;
  private int MIN_DIMENSION = 4;
  private int MAX_DIMENSION = 10000;
  private CApRgbdConfigApp m_app;
  private TxRgbdViewCamera m_rgbdCamera;
  private string m_windowTitle = RgbdResources.RGBD_WINDOW_TITLE;
  private bool m_dataChanged;
  private eImageType m_imageType;
  private double m_rgbFov;
  private int m_rgbWidth;
  private int m_rgbHeight;
  private double m_depthFov;
  private int m_depthWidth;
  private int m_depthHeight;
  private double m_depthMax;
  private double m_depthMin;
  private bool m_saveDepthImage;
  private eImageAlignment m_imageAlignment;
  private string m_outputLocation;

  public CApRgbdConfigViewModel(TxRgbdViewCamera rgbdCamera, ITxRgbdDepthReaderWriter readerWriter)
  {
    this.m_rgbdCamera = rgbdCamera;
    this.m_app = new CApRgbdConfigApp(rgbdCamera, readerWriter);
    this.InitCommands();
    this.Init(rgbdCamera);
  }

  public TxWindowCommand Apply { get; set; }

  public TxWindowCommand OpenDirectoryCommand { get; set; }

  public TxWindowCommand TakeSnapshot { get; set; }

  public TxWindowCommand<TxWindow> Browse { get; set; }

  public string WindowTitle
  {
    get => this.m_windowTitle;
    set
    {
      this.Set<string>(ref this.m_windowTitle, value, new string[1]
      {
        nameof (WindowTitle)
      });
    }
  }

  public bool DataChanged
  {
    get => this.m_dataChanged;
    set
    {
      if (this.m_dataChanged == value)
        return;
      this.m_dataChanged = value;
      ((TxWindowCommandBase) this.Apply).RaiseCanExecuteChanged();
    }
  }

  public eImageType ImageType
  {
    get => this.m_imageType;
    set => this.SetData<eImageType>(ref this.m_imageType, value, nameof (ImageType));
  }

  public double RgbFov
  {
    get => this.m_rgbFov;
    set => this.SetData<double>(ref this.m_rgbFov, value, nameof (RgbFov));
  }

  public int RgbWidth
  {
    get => this.m_rgbWidth;
    set
    {
      this.SetData<int>(ref this.m_rgbWidth, value, nameof (RgbWidth), "RgbHeightLowerBound", "RgbHeightUpperBound");
      int height;
      if (!this.AdjustHeightValue(this.m_rgbWidth, this.m_rgbHeight, out height))
        return;
      this.RgbHeight = height;
    }
  }

  public int RgbHeight
  {
    get => this.m_rgbHeight;
    set => this.SetData<int>(ref this.m_rgbHeight, value, nameof (RgbHeight));
  }

  public int RgbHeightLowerBound
  {
    get
    {
      return Math.Max((int) Math.Ceiling((double) this.m_rgbWidth / this.MAX_RATIO), this.MIN_DIMENSION);
    }
  }

  public int RgbHeightUpperBound
  {
    get
    {
      return Math.Min((int) Math.Floor((double) this.m_rgbWidth / this.MIN_RATIO), this.MAX_DIMENSION);
    }
  }

  public double DepthFov
  {
    get => this.m_depthFov;
    set => this.SetData<double>(ref this.m_depthFov, value, nameof (DepthFov));
  }

  public int DepthWidth
  {
    get => this.m_depthWidth;
    set
    {
      this.SetData<int>(ref this.m_depthWidth, value, nameof (DepthWidth), "DepthHeightLowerBound", "DepthHeightUpperBound");
      int height;
      if (!this.AdjustHeightValue(this.m_depthWidth, this.m_depthHeight, out height))
        return;
      this.DepthHeight = height;
    }
  }

  public int DepthHeight
  {
    get => this.m_depthHeight;
    set => this.SetData<int>(ref this.m_depthHeight, value, nameof (DepthHeight));
  }

  public int DepthHeightLowerBound
  {
    get
    {
      return Math.Max((int) Math.Ceiling((double) this.m_depthWidth / this.MAX_RATIO), this.MIN_DIMENSION);
    }
  }

  public int DepthHeightUpperBound
  {
    get
    {
      return Math.Min((int) Math.Floor((double) this.m_depthWidth / this.MIN_RATIO), this.MAX_DIMENSION);
    }
  }

  public double DepthMax
  {
    get => this.m_depthMax;
    set => this.SetData<double>(ref this.m_depthMax, value, nameof (DepthMax));
  }

  public double DepthMin
  {
    get => this.m_depthMin;
    set => this.SetData<double>(ref this.m_depthMin, value, nameof (DepthMin));
  }

  public bool SaveDepthImage
  {
    get => this.m_saveDepthImage;
    set
    {
      this.SetData<bool>(ref this.m_saveDepthImage, (value ? 1 : 0) != 0, nameof (SaveDepthImage));
    }
  }

  public eImageAlignment ImageAlignment
  {
    get => this.m_imageAlignment;
    set => this.SetData<eImageAlignment>(ref this.m_imageAlignment, value, nameof (ImageAlignment));
  }

  public string OutputLocation
  {
    get => this.m_outputLocation;
    set => this.SetData<string>(ref this.m_outputLocation, value, nameof (OutputLocation));
  }

  internal void SetDataChanged(bool validValue) => this.DataChanged = validValue;

  public ImageSource OpenDirectoryIcon
  {
    get
    {
      return TxImageManager.GetImageByKey("OpenDirectory").ConvertTo<ImageSource>(16U /*0x10*/, 16U /*0x10*/);
    }
  }

  private void Init(TxRgbdViewCamera rgbdCamera)
  {
    this.ImageType = rgbdCamera.Configuration.ImageCreation;
    this.RgbFov = rgbdCamera.Configuration.RgbFovAngle.AngleInDegrees;
    this.RgbWidth = rgbdCamera.Configuration.RgbdWidth;
    this.RgbHeight = rgbdCamera.Configuration.RgbdHeight;
    this.DepthFov = rgbdCamera.Configuration.DepthFovAngle.AngleInDegrees;
    this.DepthWidth = rgbdCamera.Configuration.DepthWidth;
    this.DepthHeight = rgbdCamera.Configuration.DepthHeight;
    this.DepthMax = rgbdCamera.Configuration.DepthMaximumRange;
    this.DepthMin = rgbdCamera.Configuration.DepthMinimal;
    this.SaveDepthImage = rgbdCamera.Configuration.CreateDepthPicture;
    this.ImageAlignment = rgbdCamera.Configuration.ImageAlignmentOption;
    this.OutputLocation = string.IsNullOrEmpty(rgbdCamera.Configuration.ImmediateStoragePath) || !Directory.Exists(rgbdCamera.Configuration.ImmediateStoragePath) ? TxApplication.SystemRootDirectory : rgbdCamera.Configuration.ImmediateStoragePath;
    if (!TxRgbdUtils.IsRGBDCamera(rgbdCamera.Camera))
      return;
    this.SetTitle();
    this.DataChanged = false;
  }

  private void InitCommands()
  {
    this.Browse = new TxWindowCommand<TxWindow>(new Action<TxWindow>(this.BrowseFolders));
    this.OpenDirectoryCommand = new TxWindowCommand(new Action(this.OpenDirectory));
    this.Apply = new TxWindowCommand(new Action(this.ApplyChanges), new Func<bool>(this.CanApply));
    this.TakeSnapshot = new TxWindowCommand(new Action(this.OnTakeSnapshot));
  }

  private bool AdjustHeightValue(int currentWidth, int currentHeight, out int height)
  {
    double num = (double) currentWidth / (double) currentHeight;
    height = 0;
    bool flag = false;
    if (num < this.MIN_RATIO)
    {
      height = (int) Math.Ceiling((double) currentWidth / this.MIN_RATIO);
      flag = true;
    }
    else if (num > this.MAX_RATIO)
    {
      height = (int) Math.Ceiling((double) currentWidth / this.MAX_RATIO);
      flag = true;
    }
    if (flag)
    {
      if (height < this.MIN_DIMENSION)
        height = this.MIN_DIMENSION;
      if (height > this.MAX_DIMENSION)
        height = this.MAX_DIMENSION;
    }
    return flag;
  }

  private TxRgbdCameraConfiguration GetCurrentConfiguration()
  {
    return new TxRgbdCameraConfiguration()
    {
      ImageCreation = this.ImageType,
      ImmediateStoragePath = this.OutputLocation,
      RgbFovAngle = new TxRgbdFovAngle(this.RgbFov, (TxRgbdFovAngle.AngleMeasurementUnit) 0),
      RgbdWidth = this.RgbWidth,
      RgbdHeight = this.RgbHeight,
      DepthFovAngle = new TxRgbdFovAngle(this.DepthFov, (TxRgbdFovAngle.AngleMeasurementUnit) 0),
      DepthWidth = this.DepthWidth,
      DepthHeight = this.DepthHeight,
      DepthMaximumRange = this.DepthMax,
      DepthMinimal = this.DepthMin,
      CreateDepthPicture = this.SaveDepthImage,
      ImageAlignmentOption = this.ImageAlignment
    };
  }

  private void SetTitle()
  {
    if (!TxViewCamera.op_Inequality(this.m_rgbdCamera?.Camera, (ITxObject) null))
      return;
    this.WindowTitle = $"{RgbdResources.RGBD_WINDOW_TITLE} - {this.m_rgbdCamera.Camera.Name}";
  }

  public bool SetData<T>(ref T field, T value, params string[] propertyNames)
  {
    if (!this.Set<T>(ref field, value, propertyNames))
      return false;
    this.DataChanged = true;
    return true;
  }

  private void OnTakeSnapshot()
  {
    this.m_app.TakeSnapshot(this.ImageType, this.OutputLocation, this.GetCurrentConfiguration());
  }

  private void ApplyChanges()
  {
    if (!TxRgbdUtils.IsRGBDCamera(this.m_rgbdCamera.Camera))
      this.SetTitle();
    this.m_app.ApplyChanges(this.GetCurrentConfiguration());
    this.DataChanged = false;
  }

  private bool CanApply() => this.DataChanged;

  private void BrowseFolders(TxWindow window)
  {
    using (TxFolderBrowserDialog folderBrowserDialog = new TxFolderBrowserDialog())
    {
      folderBrowserDialog.InitialFolder = this.OutputLocation;
      folderBrowserDialog.Title = RgbdResources.RGBD_WINDOW_TITLE;
      if (folderBrowserDialog.ShowDialog((Window) window) != 1)
        return;
      this.OutputLocation = folderBrowserDialog.SelectedFolder;
    }
  }

  private void OpenDirectory()
  {
    if (!Directory.Exists(this.OutputLocation))
      return;
    Process.Start(this.OutputLocation);
  }

  public class ImageTypeChangedEventArgs : EventArgs
  {
    public eImageType ImageType { get; set; }
  }
}
